<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div>
    原型链
    1.如何构成原型链 <br>

    2.原型链上属性的增删改查<br>

    <p>3.绝大多数对象的最终都会继承自Object.prototype</p>

    <p>4.object.create(原型);
    也可以创建对象
    var obj = object.create(原型);
    </p>
</div>
<script>
    // function Person() {
    //
    // }
    // console.log(Person.prototype);//构造函数的原型,打印出{constructor: ƒ}里有constructor: ƒ Person()和__proto__: Object
    // //__proto__: Object 原型中有原型
/*
    //eg:
    //Grand.prototype.__proto__ = Object.Prototype
    Grand.prototype.lastName = "wei";
    function Grand() {

    }
    console.log(Grand.prototype);
    var grand = new Grand();
    Father.prototype = grand;
    function Father() {
        this.name = "fari";
    }
    var father = new Father();
    Son.prototype = father;
    function Son() {
        this.hobby = "smoke";
    }
    var son = new Son();
    console.log(son.hobby);//smoke
    console.log(son.name);//fari
    console.log(son.lastName);//wei
    console.log(son.toString());//访问的是 Grand.prototype.__proto__ 中toString()方法

    //像上面这种情况叫做原型链

*/

/*
    Grand.prototype.lastName = "wei";
    function Grand() {

    }
    //console.log(Grand.prototype);
    var grand = new Grand();
    Father.prototype = grand;
    function Father() {
        this.name = "fari";
        this.fortune = {
            card1 : "visa"
        }
    }
    var father = new Father();
    Son.prototype = father;
    function Son() {
        this.hobby = "smoke";
    }
    var son = new Son();
    console.log(son.fortune);//{card1: "visa",__proto__: Object}
    son.fortune = 200;
    console.log(son);//Son {hobby: "smoke", fortune: 200}
    console.log(son.fortune);//200
    console.log(father.fortune);//{card1: "visa"}
    son.fortune.card2 = "master";//算是一种调用的修改
    console.log(son);//Son {hobby: "smoke", fortune: 200}
    console.log(father);//{card1: "visa",card2: "master"}
 */


/*
    Grand.prototype.lastName = "wei";
    function Grand() {

    }
    //console.log(Grand.prototype);
    var grand = new Grand();
    Father.prototype = grand;
    function Father() {
        this.name = "fari";
        this.num = 100
    }
    var father = new Father();
    Son.prototype = father;
    function Son() {
        this.hobby = "smoke";
    }
    var son = new Son();
    son.num ++;//son.num ++ ---> son.num = son.num + 1
    console.log(father.num);//100  why?????
    console.log(son.num);//101  why?????
    //因为 son.num ++ ---> son.num = son.num + 1  //son.num取的是他爹的，然后在赋值给自己
    console.log(son);//Son {hobby: "smoke", num: 101}
*/

/*
    //1.
    Person.prototype = {
        name: "a",
        sayName : function () {
            console.log(this.name);
        }
    };
    function Person() {

    }
    var person = new Person();
    person.sayName();//a
*/

/*
    //2.

    //常识：sayName() sayName里面的this指的是谁调用的这个方法，this就指向谁
    Person.prototype = {
        name: "a",
        sayName : function () {
            console.log(this.name);
        }
    };
    function Person() {
        this.name = "b";
    }
    var person = new Person();
    person.sayName();//b
    Person.prototype.sayName();//a
*/



    //这两种方式是划等号的

    var obj = {};
    console.log(obj);/// {}  __proto__: Object  也存在原型
    var obj1 = new Object();
    console.log(obj1);// {}  __proto__: Object
    //obj1.__proto__ ----> Object.prototype

    //object.create(原型);
    //也可以创建对象
    //例如：
    var o = {
        name : "han",
        age : 18
    };
    var newO = Object.create(o);//这里的o就是 newO 的原型

/*
    //所以
    Person.prototype.name = "wei";
    function Person() {

    }
    var person = Object.create(Person.prototype);

    //object.create(原型); 原型里必须是一个object or null
    var bbb = Object.create(null);
    console.log(bbb);// {} No properties 空空的啥也没有
*/

//undefined 和 null 不能调用toString()
    //包装类是可以调用toString的
    //var num = 123;
    //console.log(typeof num.toString());//string


    var num = 234;
    num.toString(); //---> new Number(num).toString;
    Number.prototype;//中是有toString()的
    //Number.prototype.__proto__ = Object.prototype;

//重写原型里面的方法，例如：重写 toString()

//1.
    Person.prototype = {
        toString : function () {
            return "hehe";
        }
    };
    function Person() {

    }
    var person = new Person();
    console.log(person.toString());//hehe

//2.
    //自带的方法修改
    Object.prototype.toString = function () {
        return "haha";
    };
    function Person1() {

    }
    var person1 = new Person1();
    console.log(person1.toString());//haha
    //自带的修改方法有
    // Object.prototype.toString
    // Array.prototype.toString
    // Boolean.prototype.toString
    // Number.prototype.toString
    // String.prototype.toString

    //eg
    var num001 = 123;
    num001.toString();//调用的就是这个Number.prototype.toString
    Number.prototype.toString.call(123);//让123去调用Number.prototype.toString这个方法。
    //[object Number]
    Boolean.prototype.toString.call(true);
    //[object Boolean]


    var obj001 = Object.create(null);
    obj001.toString = function () {
        return "其实调用了toString方法"
    };
    document.write(obj001);
    var obj002 = 123;
    document.write(obj002);//这里也调用了Number.prototype.toString
</script>

</body>
</html>
